package net.atomarrow.configs.scan;

import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import net.atomarrow.annotation.Inject;
import net.atomarrow.aop.InterceptorKeeper;
import net.atomarrow.configs.Config;
import net.atomarrow.configs.DbConfig;
import net.atomarrow.configs.LogConfig;
import net.atomarrow.db.orm.OrmContext;
import net.atomarrow.db.orm.listener.OrmListenerKeeper;
import net.atomarrow.db.tx.TransactionConfig;
import net.atomarrow.inits.InitLoadProcessor;
import net.atomarrow.ioc.ApplicationContext;
import net.atomarrow.mapping.ActionMapping;
import net.atomarrow.plugins.PluginManager;
/**
 * 配置扫描
 * @author Michael
 *
 */
public class ConfigScanner {
    
    @Inject
    private ActionMapping actionMapping;

    @Inject
    private InterceptorKeeper interceptorKeeper;
    @Inject
    private DbConfig dbConfig;
    @Inject
    private TransactionConfig transactionConfig;
    @Inject
    private InitLoadProcessor initLoadProcessor;
    @Inject
    private LogConfig logConfig;
    @Inject
    private OrmListenerKeeper ormListenerKeeper;
    @Inject
    private PluginManager pluginManager;
    
    private List<String> controllers;
    private List<String> services;
    private List<String> interceptors;
    private List<String> domains;
    private List<String> configs;
    private List<String> initLoaders;
    private List<String> ormListeners;
    private List<String> plugins;
    /**
     * 扫描所有包（或者是否按照约定只扫描controller结尾 intercepter结尾的包？）
     * 根据父类是否是指定需要加载的类进行加载
     */
    public void scan(){
        scanClasses();
        Config config = null;
        if(configs.size()>0){
            config=getConfig(configs);
            ApplicationContext.load(Config.class,config);
        }else{
            throw new RuntimeException("can not find user config file which need extends from Config Class");
        }
        printStartLog();
        interceptorKeeper.loadInterceptors(interceptors);//service加载前优先加载
        actionMapping.LoadControllers(controllers);
        ormListenerKeeper.loadListeners(ormListeners);
        pluginManager.loadPlugins(plugins);
        dbConfig.loadConfig(config);
        transactionConfig.loadConfig(config);
        logConfig.loadConfig(config);
        OrmContext.loadOrm(domains);
        //加载配置的orm Bean
        config.configOrmBean();
        initLoadProcessor.loadInits(initLoaders);
//        if(filterConfig!=null){
//            //非web容器启动的的就不需要启动加载 eg. 单元测试环境不需要加载这里
//            initLoadProcessor.executeLoad(initLoaders,filterConfig.getServletContext());
//        }
        //Service 是否需要加载？
    }
    
    
    private void printStartLog() {
        if(Config.getConfig().configStartLog()){
        	System.out.println("------------controllers-----------");
            for(String clazz:controllers){
                System.out.println(clazz);
            }
            System.out.println("------------services-----------");
            for(String clazz:services){
                System.out.println(clazz);
            }
            System.out.println("------------interceptors-----------");
            for(String clazz:interceptors){
                System.out.println(clazz);
            }
            System.out.println("------------domains-----------");
            for(String clazz:domains){
                System.out.println(clazz);
            }
            System.out.println("------------configs-----------");
            for(String clazz:configs){
                System.out.println(clazz);
            }
            System.out.println("------------initLoaders-----------");
            for(String clazz:initLoaders){
                System.out.println(clazz);
            }
            System.out.println("------------ormListeners-----------");
            for(String clazz:ormListeners){
                System.out.println(clazz);
            }
        }
	}


	private Config getConfig(List<String> configs) {
        try {
        	for(String config:configs){
        		Object obj = Class.forName(config).newInstance();
        		if(obj instanceof Config){
        			return (Config) obj;
        		}
        	}
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return null;
    }


    public void scanClasses(){
        controllers=new ArrayList<String>();
        services=new ArrayList<String>();
        interceptors=new ArrayList<String>();
        domains=new ArrayList<String>();
        configs=new ArrayList<String>();
        initLoaders=new ArrayList<String>();
        ormListeners=new ArrayList<String>();
        plugins=new ArrayList<String>();
        Enumeration<URL> founds = null;
        try {
            founds = ConfigScanner.class.getClassLoader().getResources("");
        } catch (IOException e) {
            e.printStackTrace();
        }

        while (founds.hasMoreElements()) {
            URL urlObject = founds.nextElement();
            System.out.println(urlObject.getPath());
            String path = urlObject.getPath().replaceAll("%20", " ");
            File file = new File(path);
            path=file.getPath();
            System.out.println(file.getPath());
            int prefixLen=path.length();
            parseFolders(path,prefixLen);
        }
    }
    
    public static void main(String[] args) {
//        new ConfigScanner().scan();
    }
    
    public void parseFolders(String url, int prefixLen){
        File file = new File(url);
        File[] childFiles=file.listFiles();
        if(childFiles==null){
            return;
        }
        String path;
        File child;
        for(int i=0;i<childFiles.length;i++){
            child=childFiles[i];
            path=child.getPath();
            if(child.isDirectory()){
                parseFolders(path,prefixLen);
            }
            if(path.endsWith(".class")){
                path=path.substring(0,path.length()-".class".length()).replaceAll("\\\\", ".").replaceAll("/", ".").substring(prefixLen+1);
                if(path.contains(".interceptor.")){
                    interceptors.add(path);
                }
                else if(path.contains(".controller.")){
                    controllers.add(path);
                }
                else if(path.contains(".service.")){
                    services.add(path);
                }
                else if(path.contains(".domain.")){
                    domains.add(path);
                }else if(path.contains(".config.")){
                    configs.add(path);
                }else if(path.contains(".init.")){
                    initLoaders.add(path);
                }else if(path.contains(".ormlistener.")){
                    ormListeners.add(path);
                }else if(path.contains(".plugin.")){
                    plugins.add(path);
                }
            }
        }
    }
    
    
}
